Repository navigation
fix(desktop,web): bump @xterm/* to beta.289 line for shared-atlas garble fix - #5701
Conversation
…ble fix Terminals sharing a WebGL texture atlas (same font/theme/DPR — all of ours) rendered garbled multicolor glyph fragments after another terminal triggered an atlas page merge: the consume-once invalidation flag was eaten by the first renderer to draw, leaving siblings with stale glyph->texture coords. Fixed upstream in xtermjs/xterm.js#6042 (per-renderer pageLayoutVersion), first shipped in xterm 6.1.0-beta.289 / addon-webgl 0.20.0-beta.288. The versions published 2026-07-13, inside the 3-day minimumReleaseAge window, so bunfig.toml gets a scoped, dated exclusion for @xterm/* only.
|
Ready to review this PR? Stage has broken it down into 3 individual chapters for you:
Chapters generated by Stage for commit fbb89b9 on Jul 15, 2026 6:35am UTC. |
📝 WalkthroughWalkthroughXterm dependencies are upgraded across desktop, web, host-service, and shared workspace manifests. Bun installation settings now exclude the pinned xterm packages from minimum release-age enforcement. Changesxterm dependency alignment
Estimated code review effort: 1 (Trivial) | ~5 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryBumps all
Confidence Score: 4/5Safe to merge; the changes are exact-pinned dep bumps with a clear upstream fix, verified by typecheck and the existing test suites. All package changes are exact-pinned and the entire bump is motivated by a well-documented upstream fix. The supply-chain gate bypass in bunfig.toml is time-boxed but has no automated cleanup enforcement. The transitive opentype.js 0.8.0→2.0.0 and lru-cache 6→11 upgrades inside @xterm/addon-ligatures are unlikely to surface, but they are the kinds of silent changes that can affect ligature rendering in edge cases without breaking typecheck. bunfig.toml — the
|
| Filename | Overview |
|---|---|
| bunfig.toml | Adds minimumReleaseAgeExcludes to bypass the 3-day supply-chain gate for all @xterm/* packages; comment instructs removal after 2026-07-16 but no automated enforcement exists |
| apps/desktop/package.json | Bumps all 11 @xterm/* deps from beta.220/beta.219 to beta.289/beta.288; the webgl addon trailing by one is intentional and consistent with the prior pin pattern |
| apps/web/package.json | Bumps @xterm/addon-fit and @xterm/xterm from beta.220 to beta.289; consistent with desktop update |
| packages/host-service/package.json | Bumps @xterm/headless from beta.220 to beta.289; the headless consumer's 88-test suite reportedly passes |
| packages/shared/package.json | Bumps @xterm/xterm devDependency from beta.220 to beta.289 for type-checking the shared package |
| bun.lock | Lock file reflects all @xterm/* bumps; also pulls in notable transitive dep changes: opentype.js 0.8.0→2.0.0 and lru-cache 6→11 (both via @xterm/addon-ligatures), and yallist top-level 4→5; tiny-inflate removed |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["@xterm/xterm 6.1.0-beta.289\n(core renderer + shared atlas)"] --> B["Shared WebGL Glyph Atlas\n(pageLayoutVersion — monotonic)"]
B --> C["Renderer A\n(Terminal Pane 1)"]
B --> D["Renderer B\n(Terminal Pane 2)"]
B --> E["Renderer N\n(Parked / Reused Runtime)"]
C -->|"beginFrame(): reads pageLayoutVersion"| F{Version changed?}
D -->|"beginFrame(): reads pageLayoutVersion"| F
E -->|"beginFrame(): reads pageLayoutVersion"| F
F -->|"Yes → rebuild glyph model"| G["✅ Correct texture coordinates"]
F -->|"No → reuse cached model"| G
subgraph "Before beta.220 — consume-once flag"
X["Atlas page merge fires"] --> Y["Flag set once"]
Y --> Z["First renderer consumes flag → rebuilt"]
Z --> AA["Siblings keep stale coords → garbled glyphs"]
end
subgraph "After beta.289 — monotonic pageLayoutVersion"
B
end
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A["@xterm/xterm 6.1.0-beta.289\n(core renderer + shared atlas)"] --> B["Shared WebGL Glyph Atlas\n(pageLayoutVersion — monotonic)"]
B --> C["Renderer A\n(Terminal Pane 1)"]
B --> D["Renderer B\n(Terminal Pane 2)"]
B --> E["Renderer N\n(Parked / Reused Runtime)"]
C -->|"beginFrame(): reads pageLayoutVersion"| F{Version changed?}
D -->|"beginFrame(): reads pageLayoutVersion"| F
E -->|"beginFrame(): reads pageLayoutVersion"| F
F -->|"Yes → rebuild glyph model"| G["✅ Correct texture coordinates"]
F -->|"No → reuse cached model"| G
subgraph "Before beta.220 — consume-once flag"
X["Atlas page merge fires"] --> Y["Flag set once"]
Y --> Z["First renderer consumes flag → rebuilt"]
Z --> AA["Siblings keep stale coords → garbled glyphs"]
end
subgraph "After beta.289 — monotonic pageLayoutVersion"
B
end
Comments Outside Diff (1)
-
bun.lock, line 3474 (link)opentype.jsmajor-version jump as a transitive dependency@xterm/addon-ligatures@0.11.0-beta.289now declares"opentype.js": "^2.0.0"(up from^0.8.0) and"lru-cache": "^11.3.6"(up from^6.0.0). Both are major-version upgrades in the addon's own dependency list, visible in the lock file. Since typecheck is green and the addon's API is unchanged from the application side this is unlikely to be an issue, but if ligature rendering behaves differently after this update (e.g. a font that rendered ligatures before no longer does), theopentype.js2.x migration is the first place to look.Prompt To Fix With AI
This is a comment left during a code review. Path: bun.lock Line: 3474 Comment: **`opentype.js` major-version jump as a transitive dependency** `@xterm/addon-ligatures@0.11.0-beta.289` now declares `"opentype.js": "^2.0.0"` (up from `^0.8.0`) and `"lru-cache": "^11.3.6"` (up from `^6.0.0`). Both are major-version upgrades in the addon's own dependency list, visible in the lock file. Since typecheck is green and the addon's API is unchanged from the application side this is unlikely to be an issue, but if ligature rendering behaves differently after this update (e.g. a font that rendered ligatures before no longer does), the `opentype.js` 2.x migration is the first place to look. How can I resolve this? If you propose a fix, please make it concise.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
bunfig.toml:8-20
**Temporary exclusion needs a follow-up to be removed**
`minimumReleaseAgeExcludes` bypasses the 3-day supply-chain gate and the comment marks it safe to remove after 2026-07-16 — but there is nothing enforcing that cleanup (no CI check, no lint rule, no expiry mechanism). Because `exact = true` already pins these packages, the exclusion is low-risk to leave behind, but it does permanently widen the gate for the entire `@xterm/*` scope for anyone who runs `bun install` with version resolution in the future. A follow-up PR or a TODO ticket to remove these lines after 2026-07-16 would ensure it doesn't linger.
### Issue 2 of 2
bun.lock:3474
**`opentype.js` major-version jump as a transitive dependency**
`@xterm/addon-ligatures@0.11.0-beta.289` now declares `"opentype.js": "^2.0.0"` (up from `^0.8.0`) and `"lru-cache": "^11.3.6"` (up from `^6.0.0`). Both are major-version upgrades in the addon's own dependency list, visible in the lock file. Since typecheck is green and the addon's API is unchanged from the application side this is unlikely to be an issue, but if ligature rendering behaves differently after this update (e.g. a font that rendered ligatures before no longer does), the `opentype.js` 2.x migration is the first place to look.
Reviews (1): Last reviewed commit: "fix(desktop,web): bump @xterm/* to beta...." | Re-trigger Greptile
| minimumReleaseAgeExcludes = [ | ||
| "@xterm/xterm", | ||
| "@xterm/headless", | ||
| "@xterm/addon-clipboard", | ||
| "@xterm/addon-fit", | ||
| "@xterm/addon-image", | ||
| "@xterm/addon-ligatures", | ||
| "@xterm/addon-progress", | ||
| "@xterm/addon-search", | ||
| "@xterm/addon-serialize", | ||
| "@xterm/addon-unicode11", | ||
| "@xterm/addon-webgl", | ||
| ] |
There was a problem hiding this comment.
Temporary exclusion needs a follow-up to be removed
minimumReleaseAgeExcludes bypasses the 3-day supply-chain gate and the comment marks it safe to remove after 2026-07-16 — but there is nothing enforcing that cleanup (no CI check, no lint rule, no expiry mechanism). Because exact = true already pins these packages, the exclusion is low-risk to leave behind, but it does permanently widen the gate for the entire @xterm/* scope for anyone who runs bun install with version resolution in the future. A follow-up PR or a TODO ticket to remove these lines after 2026-07-16 would ensure it doesn't linger.
Prompt To Fix With AI
This is a comment left during a code review.
Path: bunfig.toml
Line: 8-20
Comment:
**Temporary exclusion needs a follow-up to be removed**
`minimumReleaseAgeExcludes` bypasses the 3-day supply-chain gate and the comment marks it safe to remove after 2026-07-16 — but there is nothing enforcing that cleanup (no CI check, no lint rule, no expiry mechanism). Because `exact = true` already pins these packages, the exclusion is low-risk to leave behind, but it does permanently widen the gate for the entire `@xterm/*` scope for anyone who runs `bun install` with version resolution in the future. A follow-up PR or a TODO ticket to remove these lines after 2026-07-16 would ensure it doesn't linger.
How can I resolve this? If you propose a fix, please make it concise.
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
There was a problem hiding this comment.
No issues found across 6 files
Architecture diagram
sequenceDiagram
participant TA as "Terminal A (Active pane)"
participant TB as "Terminal B (Parked/reused pane)"
participant Atlas as "Shared Glyph Atlas"
participant RA as "WebGL Renderer A"
participant RB as "WebGL Renderer B"
Note over TA,TB: Same font/theme/DPR -> single WebGL texture atlas
TA->>Atlas: glyph churn triggers atlas page merge
Atlas->>Atlas: CHANGED: increment pageLayoutVersion (monotonic, no longer consume-once flag)
TA->>RA: beginFrame()
RA->>Atlas: read current pageLayoutVersion
Atlas-->>RA: version = N
RA->>RA: cached version < N -> rebuild glyph model (correct texture coordinates)
TB-->>TB: (parked - no render call)
Note over TA,TB: Later - user switches to Terminal B
TB->>RB: beginFrame()
RB->>Atlas: read current pageLayoutVersion
Atlas-->>RB: version = N
RB->>RB: cached version < N -> rebuild glyph model (correct texture coordinates)
Note over RA,RB: Both renderers retrieve updated atlas coordinates: no more stale texture reads
… build Its beta.289 bundle inlines opentype.js 2.x, which imports node:diagnostics_channel — vite externalizes node builtins in the renderer build and fails on the named import. The atlas fix doesn't touch this addon.
|
CI Build failure root-caused and fixed in fbb89b9: |
Problem
Terminal panes intermittently render garbled multicolor glyph fragments (layout intact, text unreadable), typically after heavy scrolling through colorful TUI output (Claude Code). Copying the garbled region yields correct text — the buffer is fine, the WebGL renderer is drawing from wrong texture-atlas positions.
Root cause (upstream)
xterm.js shares one WebGL glyph texture atlas across all terminals with the same font/theme/DPR — which is every pane in Superset, including parked/reused runtimes. When glyph churn triggers an atlas page merge in one terminal, the invalidation signal was a consume-once flag: the first renderer to call
beginFrame()ate it and rebuilt its model; every sibling renderer kept stale glyph→texture coordinates and drew garbage.pageLayoutVersiontracked per renderer@xterm/xterm 6.1.0-beta.289/@xterm/addon-webgl 0.20.0-beta.288(published 2026-07-13, right after merge)Same class of bug we bumped for once before (#4892/#4893).
Changes
@xterm/*deps to the beta.289 release line acrossapps/desktop,apps/web,packages/shared,packages/host-service(addon-webgl pairs at beta.288 — its numbering trails core by one, same as our previous 219/220 pin)bunfig.toml: scopedminimumReleaseAgeExcludesfor@xterm/*only — the release is 1 day old and inside our 3-day supply-chain gate. Versions are pinned exact; the exclusion is dated and safe to remove after 2026-07-16.Verification
bun run typecheck— green (35 tasks; the one docs failure was stale fumadocs codegen in a fresh worktree, passes on re-run)bun run lint— cleanpackages/sharedwheel-handler + identity-coupling tests: 26 passpackages/host-serviceterminal tests (@xterm/headless consumer): 88 passNote: the upstream issue lists a second, still-unfixed failure mode (atlas page-cap overflow → render-loop exception). This PR addresses the garbling; worth tracking upstream PR 2 of the split.
Summary by cubic
Bump
@xterm/*to the beta.289 line to pick up the shared WebGL glyph atlas fix, removing garbled multicolor text after heavy scrolling. Applies to desktop and web terminals.@xterm/xterm→6.1.0-beta.289,@xterm/addon-webgl→0.20.0-beta.288; align other@xterm/*to beta.289 across desktop, web, shared, and host-service, except@xterm/addon-ligatureswhich stays at0.11.0-beta.220due to a Vite build issue (node:diagnostics_channel).minimumReleaseAgeExcludesfor@xterm/*inbunfig.tomlto allow these releases; remove after 2026-07-16.Written for commit fbb89b9. Summary will update on new commits.
Summary by CodeRabbit